/**************************************************************************
 * This file is property of and copyright by the ALICE HLT Project        *
 * All rights reserved.                                                   *
 *                                                                        *
 * Primary Authors:                                                       *
 *   Artur Szostak <artursz@iafrica.com>                                  *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

// $Id: DisplaydHLTData.C 37070 2009-11-20 13:53:08Z aszostak $

/**
 * \ingroup macros
 * \file DisplaydHLTData.C
 * \brief Macro for displaying rootified dHLT data generated with RunChain.C
 *
 * This macro is used to display the dHLT data generated by the RunChain.C macro
 * with the "root" option for making the output data. Optionally the dHLTRawData.root
 * file which is generated during a AliRoot offline reconstruction can also be
 * displayed using this macro.
 * After having generated the dHLT raw data file (called <i>output.root</i> for example)
 * the following command can be executed in an alieve session to display both
 * MUON and dHLT data:
 * \code
 *   > gSystem->Load("libAliHLTMUON.so");
 *   > .L $ALICE_ROOT/EVE/macros/alieve_init.C
 *   > .L $ALICE_ROOT/EVE/alice-macros/event_goto.C
 *   > .L $ALICE_ROOT/EVE/alice-macros/MUON_displayData.C
 *   > .L $ALICE_ROOT/HLT/MUON/macros/DisplaydHLTData.C
 *   > alieve_init("OCDBpath","DataPath",EventNumber);
 *   > MUON_displayData(1,1,1);
 *   > DisplaydHLTData("output.root");
 * \endcode
 * Where <i>OCDBpath</i> should be replaced by the path to the OCDB database,
 * <i>DataPath</i> should be the directory of the raw data or raw data root file and
 * <i>EventNumber</i> is the event number to load.
 *
 * \author Artur Szostak <artursz@iafrica.com>
 */

#if !defined(__CINT__) || defined(__MAKECINT__)
#include "AliEveEventManager.h"
#include "AliHLTMUONTriggerRecord.h"
#include "AliHLTMUONRecHit.h"
#include "AliHLTMUONMansoTrack.h"
#include "AliHLTMUONEvent.h"
#include "TEveManager.h"
#include "TEveElement.h"
#include "TEvePointSet.h"
#include "TEveStraightLineSet.h"
#include "TArrayD.h"
#include "TFile.h"
#include "TString.h"
#include "TClassTable.h"
#include "TSystem.h"
#include <iostream>
using std::cerr;
using std::endl;
#endif


TFile* gDHLTFile = NULL;

void FillData(Int_t eventId);


void DisplaydHLTData(const char* dHLTfilename = "output.root")
{
	// Display dHLT data.
	
	if (gClassTable->GetID("AliHLTMUONEvent") < 0)
	{
		gSystem->Load("libAliHLTMUON.so");
	}
	
	if (AliEveEventManager::GetMaster() == NULL)
	{
		cerr << "ERROR: alieve event not initialised, use alieve_init(...)" << endl;
		return;
	}
	
	gEve->DisableRedraw();
	
	TString filename = dHLTfilename;
	TString tmpfilename = filename;
	if (gSystem->FindFile("", tmpfilename) == NULL)
	{
		tmpfilename = filename;
		if (gSystem->FindFile(".", tmpfilename) == NULL)
		{
			TString filename = TString(AliEveEventManager::GetMaster()->GetTitle());
			filename += "/";
			filename += dHLTfilename;
		}
	}
	if (gDHLTFile == NULL)
	{
		gDHLTFile = new TFile(filename.Data(), "READ");
	}
	else if (filename != gDHLTFile->GetName())
	{
		delete gDHLTFile;
		gDHLTFile = new TFile(filename.Data(), "READ");
	}
	
	FillData(AliEveEventManager::GetMaster()->GetEventId());
	
	gEve->Redraw3D(kTRUE);
	gEve->EnableRedraw();
}


void FillData(TEveElementList* list, const AliHLTMUONTriggerRecord* trigrec)
{
	// Count the number of points in the trigger record.
	Int_t pointCount = 0;
	for (int i = 11; i <= 14; ++i)
	{
		if (trigrec->Hit(i) != TVector3(0,0,0)) ++pointCount;
	}
	
	// Create and fill the point set for the trigger record.
	TEvePointSet* pointset = new TEvePointSet(pointCount);
	pointset->SetName(Form("TriggerRecord%d", trigrec->Id()));
	pointset->SetTitle(Form("dHLT trigger record ID = %d", trigrec->Id()));
	pointset->SetMarkerStyle(28);
	pointset->SetMarkerColor(kYellow);
	pointset->SetMarkerSize(3);
	Int_t ipnt = 0;
	for (int i = 11; i <= 14; ++i)
	{
		if (trigrec->Hit(i) == TVector3(0,0,0)) continue;
		pointset->SetPoint(ipnt, trigrec->Hit(i).X(), trigrec->Hit(i).Y(), trigrec->Hit(i).Z());
		++ipnt;
	}
	
	list->AddElement(pointset);
}


void FillData(TEveElementList* list, const AliHLTMUONMansoTrack* track)
{
	// Count the points in the track.
	Int_t pointCount = 0;
	for (int i = 7; i <= 10; ++i)
	{
		const AliHLTMUONRecHit* hit = track->Hit(i);
		if (hit != NULL) ++pointCount;
	}
	const AliHLTMUONTriggerRecord* trigrec = track->TriggerRecord();
	if (trigrec != NULL)
	{
		for (int i = 11; i <= 14; ++i)
		{
			if (trigrec->Hit(i) != TVector3(0,0,0)) ++pointCount;
		}
	}
	
	// Create and fill the point set for the track.
	TEvePointSet* pointset = new TEvePointSet(pointCount);
	pointset->SetName(Form("Track%d", track->Id()));
	pointset->SetTitle(Form("dHLT track ID = %d", track->Id()));
	if (track->Id() != -1)
	{
		pointset->SetMarkerStyle(20);
		pointset->SetMarkerColor(kGreen);
		pointset->SetMarkerSize(1.5);
	}
	else
	{
		pointset->SetMarkerStyle(28);
		pointset->SetMarkerColor(kYellow);
		pointset->SetMarkerSize(3);
	}
	Int_t ipnt = 0;
	if (trigrec != NULL)
	{
		for (int i = 11; i <= 14; ++i)
		{
			if (trigrec->Hit(i) == TVector3(0,0,0)) continue;
			pointset->SetPoint(ipnt, trigrec->Hit(i).X(), trigrec->Hit(i).Y(), trigrec->Hit(i).Z());
			++ipnt;
		}
	}
	for (int j = 7; j <= 10; ++j)
	{
		const AliHLTMUONRecHit* hit = track->Hit(j);
		if (hit == NULL) continue;
		pointset->SetPoint(ipnt, hit->X(), hit->Y(), hit->Z());
		++ipnt;
	}
	
	for (int j = 7; j <= 10; ++j)
	{
		if (track->RoIRadius(j) == -1) continue;
		TEveStraightLineSet* roi = new TEveStraightLineSet(
				Form("RoI%d", j),
				Form("Region of interest for chamber %d", j)
			);
		Float_t p0x = track->RoICentre(j).X() + track->RoIRadius(j);
		Float_t p0y = track->RoICentre(j).Y();
		Float_t p0z = track->RoICentre(j).Z();
		Float_t p1x = p0x;
		Float_t p1y = p0y;
		Float_t p1z = p0z;
		for (int i = 0; i < 32; ++i)
		{
			Double_t t = Double_t(i) / 32. * 2. * TMath::Pi();
			Float_t p2x = track->RoICentre(j).X() + track->RoIRadius(j)*cos(t);
			Float_t p2y = track->RoICentre(j).Y() + track->RoIRadius(j)*sin(t);
			Float_t p2z = track->RoICentre(j).Z();
			roi->AddLine(p1x, p1y, p1z, p2x, p2y, p2z);
			p1x = p2x;
			p1y = p2y;
			p1z = p2z;
		}
		roi->AddLine(p1x, p1y, p1z, p0x, p0y, p0z);
		pointset->AddElement(roi);
	}
	
	list->AddElement(pointset);
}


void FillData(Int_t eventId)
{
	AliHLTMUONEvent* dhltEvent = dynamic_cast<AliHLTMUONEvent*>( gDHLTFile->Get(Form("AliHLTMUONEvent;%d", eventId+1)) );
	if (dhltEvent == NULL)
	{
		cerr << "ERROR: Could not find dHLT data for event " << eventId << endl;
		return;
	}
	
	TEveElementList* list = new TEveElementList("dHLTData", "dHLT data");
	gEve->AddElement(list);
	
	TArrayD px, py, pz;
	for (int i = 0; i < dhltEvent->DataObjects().GetEntriesFast(); i++)
	{
		if (dhltEvent->DataObjects()[i]->IsA() == AliHLTMUONRecHit::Class())
		{
			const AliHLTMUONRecHit* hit = dynamic_cast<const AliHLTMUONRecHit*>( dhltEvent->DataObjects()[i] );
			px.Set(px.GetSize()+1);
			py.Set(py.GetSize()+1);
			pz.Set(pz.GetSize()+1);
			px[px.GetSize()-1] = hit->X();
			py[py.GetSize()-1] = hit->Y();
			pz[pz.GetSize()-1] = hit->Z();
			continue;
		}
		else if (dhltEvent->DataObjects()[i]->IsA() == AliHLTMUONTriggerRecord::Class())
		{
			const AliHLTMUONTriggerRecord* trigrec = dynamic_cast<const AliHLTMUONTriggerRecord*>( dhltEvent->DataObjects()[i] );
			FillData(list, trigrec);
		}
		else if (dhltEvent->DataObjects()[i]->IsA() == AliHLTMUONMansoTrack::Class())
		{
			const AliHLTMUONMansoTrack* track = dynamic_cast<const AliHLTMUONMansoTrack*>( dhltEvent->DataObjects()[i] );
			FillData(list, track);
		}
	}
	
	TEvePointSet* mps = new TEvePointSet(px.GetSize());
	mps->SetName("RecHits");
	mps->SetTitle("dHLT reconstructed hits");
	mps->SetMarkerStyle(28);
	mps->SetMarkerColor(kYellow);
	mps->SetMarkerSize(3);
	for (int i = 0; i < px.GetSize(); ++i)
	{
		mps->SetPoint(i, px[i], py[i], pz[i]);
	}
	list->AddElement(mps);
}
